package server;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.LinkedList;

import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.security.cert.X509Certificate;

import Exceptions.NixonExeception;

import util.Record;
import util.SSLClientServer;

public class Server extends SSLClientServer {
	private PermissionHandler ph;
	private SSLServerSocket soc;

	public Server(int port) {
		super(port, null);
		setUpKeyManager("ServerKeystore/KeystoreServer.jks", "password");
		ph = new PermissionHandler();
		SSLServerSocketFactory factory = ctx.getServerSocketFactory();
		 try {
			soc = (SSLServerSocket) factory.createServerSocket(port);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		soc.setNeedClientAuth(true);
	}

	/**
	 * Sets up and runs the server
	 */
	public void run() {
		try {
		
			socket = (SSLSocket) soc.accept();

			socketInput = new BufferedReader(new InputStreamReader(
					socket.getInputStream()));
			out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
					socket.getOutputStream())));
			if (out.checkError())
				System.out
						.println("SSLSocketClient: java.io.PrintWriter error");

			SSLSession session = socket.getSession();
			X509Certificate cert = null;
			try {
				cert = (X509Certificate) session.getPeerCertificateChain()[0];
			} catch (SSLPeerUnverifiedException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			String subject = cert.getSubjectDN().getName();
			String[] temp = subject.split(",");
			temp = temp[0].split("=");
			String pNbr = temp[1];

			boolean userSession = true;
			
			if (ph.login(pNbr)) {
				while (userSession) {
					try {
						String inputLine = socketInput.readLine();
						if(inputLine == null){
							break;
						}
						String line[] = inputLine.split(":");
						if(line.length < 2){
							out.println("How did you manage this?" +  "\nEND");
							out.flush();
							continue;
						}
						Record r = null;
						switch (Integer.parseInt(line[0])) {
						case (1):
							r = ph.fetchRecordForRead(line[1]);
							out.println(r.recordTransfer() + "\nEND");
							out.flush();
							break;
						case (2):
							LinkedList<Record> recList = ph
									.fetchRecordForReadByPnbr(line[1]);
							for (Record rec : recList) {
								out.println(rec.recordTransfer());
								out.println();
								out.flush();
							}
							out.println("\nEND");
							out.flush();
							break;
						case (3):
							out.println("How did you manage this? It isn't even implemented!" +  "\nEND");
							out.flush();
							break;
						case (4):
							if(ph.deleteRecord(line[1])){
								out.println("Success" + "\nEND");
							}else{
								out.println("Failed" + "\nEND");
							}							
							out.flush();
							break;
						case (5):
							ph.createDocument(line[1], line[2], line[3]);
							r = ph.fetchRecordForRead(line[2]);
							out.println(r.recordTransfer() + "\nEND");
							out.flush();
							break;
						}
					} catch (NixonExeception e) {
						out.println(e.toString() + "\nEND");
						out.flush();
					}
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
			System.exit(1);
			// TODO Auto-generated catch block

		}

	}

}
